﻿using Domain.Model;
using Infrastructure.AggregateBase;
using Infrastructure.UniOfWorkBase;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Domain
{
    public class GoLifeDbContext : DbContext
    {
        #region 初始化
        public Guid guid = Guid.NewGuid();
        public IConfiguration Configuration { get; set; }
        public override int SaveChanges()
        {
            SetSystemField();
            return base.SaveChanges();
        }
        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            SetSystemField();
            return base.SaveChangesAsync();
        }

        private void SetSystemField()
        {
            foreach (var item in ChangeTracker.Entries())
            {
                if (item.Entity is IEntity)
                {
                    var entity = (IEntity)item.Entity;
                    //添加操作
                    if (item.State == EntityState.Added)
                    {
                        entity.UT = entity.CT = DateTime.Now;
                    }
                    //修改操作
                    else if (item.State == EntityState.Modified)
                    {
                        entity.UT = DateTime.Now;
                    }
                }

            }
        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseLazyLoadingProxies();                
#if DEBUG
                optionsBuilder.UseMySql("Database=golife;Data Source=81.68.83.153;Port=3306;User Id=golife;Password=xNFRPGDY2R8wXHCi;Charset=utf8;Pooling=true;MinimumPoolSize=20;MaximumPoolSize=100;Connect Timeout=600;");

                var loggerFactory = new LoggerFactory();
                loggerFactory.AddProvider(new Infrastructure.Log.EFLoggerProvider());
                optionsBuilder.UseLoggerFactory(loggerFactory);
#else
                optionsBuilder.UseMySql(Configuration["DbConn"]);
# endif
                optionsBuilder.ConfigureWarnings(o =>
                {
                    o.Ignore(CoreEventId.LazyLoadOnDisposedContextWarning);
                    o.Ignore(CoreEventId.DetachedLazyLoadingWarning);
                });
            }

            base.OnConfiguring(optionsBuilder);
        }

        #endregion

        /// <summary>
        /// 配置索引与关系
        /// </summary>
        /// <param name="modelBuilder"></param>
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<UserInfoAggregate>().HasIndex(s => s.Phone).IsUnique();
            modelBuilder.Entity<UserInfoAggregate>().HasIndex(s => s.InviteCode).IsUnique();
            modelBuilder.Entity<UserInfoAggregate>().HasIndex(s => s.WxUnionID).IsUnique();

            modelBuilder.Entity<RealNameInfo>().HasIndex(s => s.CardNO);

            modelBuilder.Entity<WalletAggregate>().HasIndex(s => s.UserID).IsUnique();

            modelBuilder.Entity<InComeWalletLogAggregate>().HasBaseType<WalletLog>().HasDiscriminator<string>("LogType").HasValue("InCome");
            modelBuilder.Entity<ChargeWalletLogAggregate>().HasBaseType<WalletLog>().HasDiscriminator<string>("LogType").HasValue("Charge");
            modelBuilder.Entity<InComeWalletLogAggregate>().HasBaseType<WalletLog>().HasIndex(s => s.UserID);
            modelBuilder.Entity<InComeWalletLogAggregate>().HasBaseType<WalletLog>().HasIndex(s => s.CT);

            modelBuilder.Entity<SmsCodeAggregate>().HasIndex(s => s.Phone);
            modelBuilder.Entity<DicAggregate>().HasIndex(s => new { s.GroupName, s.KeyName });
            modelBuilder.Entity<TaskAggregate>().HasIndex(s => s.UserID);
            modelBuilder.Entity<TaskAggregate>().HasIndex(s => s.FinishTime);
            modelBuilder.Entity<TaskAggregate>().HasIndex(s => s.CategoryID);

            modelBuilder.Entity<TaskTakeAggregate>().HasIndex(s => s.UserID);
            modelBuilder.Entity<TaskTakeAggregate>().HasIndex(s=>s.TaskID);
            modelBuilder.Entity<TaskTakeAggregate>().HasIndex(s => s.Identity);
            modelBuilder.Entity<TaskTakeAggregate>().HasIndex(s => s.TaskUserID);
            //modelBuilder.Entity<TaskTakeAggregate>().OwnsOne(s => s.TaskSrcData);

            modelBuilder.Entity<BlackListAggregate>().HasIndex(s => s.UserID).IsUnique();
            modelBuilder.Entity<PayCallBackLogAggregate>().HasIndex(s => s.SerialNO).IsUnique();
            modelBuilder.Entity<PayCallBackLogAggregate>().HasIndex(s => s.InstitutionNO).IsUnique();

            modelBuilder.Entity<LevelLog>().Property("LogType").HasMaxLength(10);
            modelBuilder.Entity<TraderLevelLog>().HasBaseType<LevelLog>().HasDiscriminator<string>("LogType").HasValue("Trader");
            modelBuilder.Entity<TraderLevelLog>().HasIndex(s => s.CT);
            modelBuilder.Entity<UserLevelLog>().HasBaseType<LevelLog>().HasDiscriminator<string>("LogType").HasValue("User");
            modelBuilder.Entity<UserLevelLog>().HasIndex(s => s.CT);

            modelBuilder.Entity<GeTuiRelationAggregate>().HasIndex(s => s.UserID);

            modelBuilder.Entity<WithDrawAggregate>().HasIndex(s => s.UserID);
            modelBuilder.Entity<WithDrawAggregate>().HasIndex(s => s.Identity);

            modelBuilder.Entity<WxMiniAggregate>().HasIndex(s => s.UserID);
            modelBuilder.Entity<WxMiniAggregate>().HasIndex(s => s.WxUnionID);
            modelBuilder.Entity<WxMiniAggregate>().HasIndex(s => s.WxOpenID);

            modelBuilder.Entity<RecommendListAggregate>().HasIndex(s => s.TaskID);
            modelBuilder.Entity<RecommendListAggregate>().HasIndex(s => s.EndTime);
            modelBuilder.Entity<RecommendListAggregate>().HasIndex(s => s.SetTime);

            modelBuilder.Entity<TXJLLogAggregate>().HasIndex(s => s.UserID);
            modelBuilder.Entity<TXJLLogAggregate>().HasIndex(s => s.WithDrawIdentity).IsUnique();

            modelBuilder.Entity<MessageAggregate>().HasIndex(s => s.CT);
            modelBuilder.Entity<MessageUserAggregate>().HasIndex(s => s.UserID);

            modelBuilder.Entity<RewardListAggregate>().HasIndex(s => s.Month);

            base.OnModelCreating(modelBuilder);
        }
        
        public override void Dispose()
        {
            base.DisposeAsync().GetAwaiter().GetResult();
            base.Dispose();
        }
        public override ValueTask DisposeAsync()
        {
            return new ValueTask(Task.CompletedTask);
            //return base.DisposeAsync();
        }


        public DbSet<UserInfoAggregate> UserInfoAggregates { get; set; }
        public DbSet<LoginLogAggregate> LoginLogs { get; set; }
        public DbSet<TraderLevelLog> TraderLevelLogs { get; set; }
        public DbSet<UserLevelLog> UserLevelLogs { get; set; }
        public DbSet<UserProp> UserProps { get; set; }
        public DbSet<AdminAggregate> AdminAggregates { get; set; }
        public DbSet<RoleAggregate> RoleAggregates { get; set; }
        public DbSet<AdminRole> AdminRoles { get; set; }
        public DbSet<SmsCodeAggregate> SmsCodeAggregates { get; set; }
        public DbSet<DicAggregate> DicAggregates { get; set; }
        public DbSet<WalletAggregate> WalletAggregates { get; set; }
        public DbSet<InComeWalletLogAggregate> InComeWalletLogAggregates { get; set; }
        public DbSet<ChargeWalletLogAggregate> ChargeWalletLogAggregates { get; set; }
        public DbSet<InviteLogAggregate> InviteLogs { get; set; }
        public DbSet<RealNameInfo> RealNameInfos { get; set; }
        public DbSet<BlackListAggregate> BlackListAggregates { get; set; }
        public DbSet<TaskAggregate> TaskAggregates { get; set; }
        public DbSet<TaskAudit> TaskAudits { get; set; }
        public DbSet<TaskCategoryAggregate> TaskCategoryAggregates { get; set; }
        public DbSet<TaskTakeAggregate> TaskTakeAggregates { get; set; }
        public DbSet<TaskLogAggregate> TaskLogAggregates { get; set; }
        public DbSet<CapitalFlowAggregate> CapitalFlowAggregates { get; set; }
        public DbSet<PayCallBackLogAggregate> PayCallBackLogAggregates { get; set; }
        public DbSet<BannerAggregate> BannerAggregates { get; set; }
        public DbSet<GeTuiRelationAggregate> GeTuiRelationAggregates { get; set; }
        public DbSet<WithDrawAggregate> WithDrawAggregates { get; set; }
        public DbSet<WxMiniAggregate> WxMiniAggregates { get; set; }
        public DbSet<UserPropBuyLogAggregate> UserPropBuyLogAggregates { get; set; }
        public DbSet<UserPropUseLogAggregate> UserPropUseLogAggregates { get; set; }
        public DbSet<RecommendListAggregate> RecommendListAggregates { get; set; }
        public DbSet<TXJLLogAggregate> TXJLLogAggregates { get; set; }
        public DbSet<FinancialAggregate> FinancialAggregates { get; set; }

        public DbSet<MessageAggregate> MessageAggregates { get; set; }
        public DbSet<MessageUserAggregate> MessageUserAggregates { get; set; }
        public DbSet<RewardListAggregate> RewardListAggregates { get; set; }
        public DbSet<KFQAAggregate> KFQAAggregates { get; set; }        

    }
}
